﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Configuration;
using System.Data.OleDb;
using System.Collections;


namespace Sinacor.Tools.Dado
{
    public class DadoPorta
    {
        private string conexao = string.Empty;
        private Hashtable colunas = new Hashtable();

        public DadoPorta() 
        {
            conexao = ConfigurationManager.AppSettings["bancoEmUso"];
            carregarColunas(conexao);
        }
        
        private void carregarColunas(string colunas)
        {
            string[] NomesColunas = ConfigurationManager.AppSettings[this.conexao].Split(';');
            string [] valor;
            for (int i = 0; i < NomesColunas.Length; i++)
            {
                if (! string.IsNullOrEmpty(NomesColunas[i].Trim()))
                {
                    valor = NomesColunas[i].Split('=');
                    if (valor.Length == 2 && valor[0] != string.Empty && valor[1] != string.Empty)
                    {
                        this.colunas.Add(valor[0], valor[1]);
                    }
                }
            }
        }

        private List<Sinacor.Tools.Entidade.Modulo> getPorts(string comando)
        {
            List<Sinacor.Tools.Entidade.Modulo> listaModulos = new List<Sinacor.Tools.Entidade.Modulo>();
            Sinacor.Tools.Entidade.Modulo modulo = null;

            using (OleDbCommand cmd = this.getCommand(comando, CommandType.Text))
            {
                using (OleDbDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
                {
                    
                    //consulta feita pelo índice por causa do excel
                    
                    while (reader.Read())
                    {
                        modulo = new Sinacor.Tools.Entidade.Modulo();
                        if (reader[0] != DBNull.Value)
                            modulo.Nome = Convert.ToString(reader[Convert.ToInt32(this.colunas["Nome"])]);

                        if (reader[1] != DBNull.Value)
                            modulo.Submodulo = Convert.ToString(reader[Convert.ToInt32(this.colunas["Submodulo"])]);

                        if (reader[2] != DBNull.Value)
                            modulo.Servico = Convert.ToString(reader[Convert.ToInt32(this.colunas["Servico"])]);

                        if (reader[4] != DBNull.Value)
                            modulo.Porta = Convert.ToInt32(reader[Convert.ToInt32(this.colunas["Porta"])]);

                        if (reader[3] != DBNull.Value)
                            modulo.PortaMex = Convert.ToInt32(reader[Convert.ToInt32(this.colunas["PortaMex"])]);

                        //só adiciona na lista se possui nome, submodulo e serviço
                        //if (modulo.PortaMex != 0 && modulo.Porta != 0)
                        //só adiciona na lista se possui porta
                        if (modulo.Porta > 0)
                            listaModulos.Add(modulo);
                    }
                    reader.Close();
                }
            }

            return listaModulos;
        }

        private string getInsert(Sinacor.Tools.Entidade.Modulo pModulo)
        {
            string insert = conexao == "EXCEL" ?
            string.Format("INSERT INTO [01$] VALUES ('{0}', '{1}', '{2}', {3}, {4}, '', '', '')", pModulo.Nome, pModulo.Submodulo, pModulo.Servico,
            pModulo.PortaMex, pModulo.Porta) :
            string.Format("INSERT INTO TFWDCONTROLEPORTA (MODULO, SUBMODULO, SERVICO, PORTAMEX, PORTA) VALUES ('{0}', '{1}', '{2}', {3}, {4})", pModulo.Nome, pModulo.Submodulo, string.IsNullOrEmpty(pModulo.Servico) ? " " : pModulo.Servico, pModulo.PortaMex, pModulo.Porta);
            return insert;
        }

        private string getUpdate(Sinacor.Tools.Entidade.Modulo pModuloOld, Sinacor.Tools.Entidade.Modulo pModuloNew)
        {
            //não leva mais em consideração o nome do serviço
            //return string.Format("UPDATE [01$] SET Módulo = '{0}', SubMódulo = '{1}', Serviço = '{2}' WHERE Módulo = '{3}' AND SubMódulo = '{4}' AND Serviço = '{5}'", pModuloNew.Nome, pModuloNew.Submodulo, pModuloNew.Servico, pModuloOld.Nome, pModuloOld.Submodulo, pModuloOld.Servico);
            string update = conexao == "EXCEL" ?
                string.Format("UPDATE [01$] SET Módulo = '{0}', SubMódulo = '{1}' WHERE Módulo = '{3}' AND SubMódulo = '{4}' ", pModuloNew.Nome, pModuloNew.Submodulo, pModuloNew.Servico, pModuloOld.Nome, pModuloOld.Submodulo, pModuloOld.Servico) :
                string.Format("UPDATE TFWDCONTROLEPORTA SET MODULO = '{0}', SUBMODULO = '{1}' WHERE MODULO = '{3}' AND SUBMODULO = '{4}' ", pModuloNew.Nome, pModuloNew.Submodulo, pModuloNew.Servico, pModuloOld.Nome, pModuloOld.Submodulo, pModuloOld.Servico);
            return update;
        }

        public void atualizar(Sinacor.Tools.Entidade.Modulo pModuloOld, Sinacor.Tools.Entidade.Modulo pModuloNew)
        {
            OleDbCommand cmd = null;
            try
            {
                using (cmd = this.getCommand(this.getUpdate(pModuloOld, pModuloNew), CommandType.Text))
                {
                    cmd.ExecuteNonQuery();
                    cmd.Connection.Close();
                }
            }
            //ainda não tem o que ser feito com a exception de banco
            catch (OleDbException ex)
            {
                if (cmd != null && cmd.Connection != null && cmd.Connection.State != ConnectionState.Closed)
                {
                    cmd.Connection.Close();
                }
            }
        }

        public void incluir(Sinacor.Tools.Entidade.Modulo pModulo)
        {
            OleDbCommand cmd = null;
            try
            {
                using (cmd = this.getCommand(this.getInsert(pModulo), CommandType.Text))
                {
                    cmd.ExecuteNonQuery();
                    cmd.Connection.Close();
                }
            }
            //ainda não tem o que ser feito com a exception de banco
            catch (OleDbException ex)
            {
                if (cmd != null && cmd.Connection != null && cmd.Connection.State != ConnectionState.Closed)
                {
                    cmd.Connection.Close();
                }
            }
        }
        
        public List<Sinacor.Tools.Entidade.Modulo> getPorts()
        {
            return this.getPorts(this.getQuery());
        }

        private string getQuery()
        {
            //o uso do asterisco (*) é por que nem sempre o excel retorna todas as suas colunas.
            //para o uso do oracle poderiam ser utilizadas as colunas
            string select = conexao == "EXCEL" ? "SELECT * FROM [01$]" :
                           "SELECT * FROM TFWDCONTROLEPORTA ORDER BY MODULO, SUBMODULO, SERVICO";
            return select;
        }



        private void printarDadosReaderReader(OleDbDataReader reader)
        {
            string colunas = string.Empty;
            for (byte i = 0; i < reader.FieldCount; i++)
            {
                colunas += Convert.ToString(reader[i]) + ";";
            }
            System.Diagnostics.Debug.WriteLine(colunas);
        }

        
        
        private OleDbCommand getCommand(string comando, CommandType tipo)
        {
            OleDbConnection con = new OleDbConnection();
            con.ConnectionString = getConnectionString();
            con.Open();
            OleDbCommand cmd = con.CreateCommand();
            cmd.CommandText = comando;
            cmd.CommandType = tipo;
            return cmd;
        }

        private string getConnectionString()
        {
            conexao = ConfigurationManager.AppSettings["bancoEmUso"];
            if (string.IsNullOrEmpty(conexao))
            {
                throw new Exception("A chave que define qual string de conexão deverá ser usada não está definida no web.config");
            }
            validaConexoes(conexao);

            return ConfigurationManager.ConnectionStrings[conexao].ConnectionString;           
        }

        private void validaConexoes(string conexao)
        {
            //se o excel fosse banco de dados essas gambiarras não existiriam
            if (!(conexao == "ORACLE" || conexao == "EXCEL"))
                throw new Exception("Os bancos de dados cadastrados no Web.config devem ser ORACLE ou EXCEL!");
        }


        #region "Código para exportar para o excel"
        
        /// <summary>
        /// este método só deve ser usado por processos internos
        /// </summary>
        /// <param name="comando"></param>
        /// <param name="tipo"></param>
        /// <param name="banco"></param>
        /// <returns></returns>
        private OleDbCommand getCommand(string comando, CommandType tipo, string banco)
        {
            OleDbConnection con = new OleDbConnection();
            con.ConnectionString = ConfigurationManager.ConnectionStrings[banco].ConnectionString;
            con.Open();
            OleDbCommand cmd = con.CreateCommand();
            cmd.CommandText = comando;
            cmd.CommandType = tipo;
            return cmd;
        }


        public void exportarParaOracle()
        {
            conexao = "ORACLE";
            List<Sinacor.Tools.Entidade.Modulo> listaModulosExcel = this.getPorts(this.getQuery());
            OleDbCommand cmd = null;
            
                int qtdeLoops = listaModulosExcel.Count;
                cmd = this.getCommand(string.Empty, CommandType.Text, conexao);
                for (int i = 0; i < qtdeLoops; i++)
                {
                    try
                    {
                        cmd.CommandText = this.getInsert(listaModulosExcel[i]);
                        cmd.ExecuteNonQuery();
                    }
                    catch
                    {

                        //foda-se
                    }
                }
        }
        #endregion
    }
}
